package arithmetic.thread.bolckqueen;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.locks.LockSupport;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * 我的阻塞队列3, LockSupport写法 condition写法 await,  signal
 *
 * @author jiangfeng on 2022/4/9
 */
public class MyBlockQueen4<T> implements MyBlockQueenInterface<T> {

    public static Logger log = LoggerFactory.getLogger(MyBlockQueen4.class);


    private final List<T> arrays;
    private final Integer maxLength;

    private final Set<Thread> consumerThreads = new HashSet<>();
    private final Set<Thread> productorsThreads = new HashSet<>();


    /**
     * 初始化
     */
    public MyBlockQueen4(int maxLength) {
        this.maxLength = maxLength;
        arrays = Collections.synchronizedList(new ArrayList<T>(maxLength));
    }

    @Override
    // 关键点在于如何阻塞??,
    public void put(T t) {
        // 最大数量需要阻塞
        while (arrays.size() == maxLength) {
            productorsThreads.add(Thread.currentThread());
            // 进入休眠,唤醒别的线程
            //LockSupport.park(LockSupport.parkNanos(1000*1000*1000L));
            // 防死锁
            LockSupport.parkNanos(1000 * 1000 * 1000L);
        }
        arrays.add(t);
        log.info("{},add: {}", Thread.currentThread().getName(), t);
        // 添加完了可以唤醒,消费者了
        if (consumerThreads.size() > 0) {
            // 唤醒第一个消费者, 如果有
            Thread next = consumerThreads.stream().iterator().next();
            LockSupport.unpark(next);
            consumerThreads.remove(next);
        }
    }

    @Override
    public T take() {
        // 没有元素需要阻塞
        while (arrays.size() == 0) {
            // 进入休眠
            consumerThreads.add(Thread.currentThread());
            // 等一秒,再次尝试
            LockSupport.parkNanos(1000 * 1000 * 1000L);
        }
        T remove = arrays.remove(arrays.size() - 1);
        log.info("{},take: {}", Thread.currentThread().getName(), remove);
        // 消费完了 可以唤醒生产者继续了.
        if (productorsThreads.size() > 0) {
            // 唤醒第一个生产者, 如果有
            Thread next = productorsThreads.stream().iterator().next();
            LockSupport.unpark(next);
            productorsThreads.remove(next);
        }

        // 唤醒别的线程
        return remove;


    }

    public static void main(String[] args) {
        int i = 0;
        while (true) {
            // 进入休眠
            System.out.println(i++);
            // 等一秒,再次尝试
            //LockSupport.parkNanos(1000*1000*1000L);
            // 直到一个固定时间?
            LockSupport.parkUntil(1L);
        }
    }


}
